package com.xuecheng.media.service.impl;

import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.vod.model.v20170321.GetPlayInfoResponse;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.xuecheng.api.media.model.dto.MediaDTO;
import com.xuecheng.api.media.model.qo.QueryMediaModel;
import com.xuecheng.api.media.model.vo.MediaVO;
import com.xuecheng.common.domain.code.CommonErrorCode;
import com.xuecheng.common.domain.page.PageRequestParams;
import com.xuecheng.common.domain.page.PageVO;
import com.xuecheng.common.domain.response.RestResponse;
import com.xuecheng.common.enums.StatusEnum;
import com.xuecheng.common.enums.common.AuditEnum;
import com.xuecheng.common.enums.common.CommonEnum;
import com.xuecheng.common.enums.content.CourseAuditEnum;
import com.xuecheng.common.exception.ExceptionCast;
import com.xuecheng.common.util.SecurityUtil;
import com.xuecheng.common.util.StringUtil;
import com.xuecheng.media.agent.MediaTeacherAgent;
import com.xuecheng.media.common.constant.MediaErrorCode;
import com.xuecheng.media.common.utils.AliyunVODUtil;
import com.xuecheng.media.convert.MediaConvert;
import com.xuecheng.media.entity.Media;
import com.xuecheng.media.mapper.MediaMapper;
import com.xuecheng.media.service.MediaService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.ObjectUtils;

import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 * 媒资信息 服务实现类
 * </p>
 *
 * @author itcast
 */
@Slf4j
@Service
public class MediaServiceImpl extends ServiceImpl<MediaMapper, Media> implements MediaService {

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private MediaTeacherAgent mediaTeacherAgent;


    @Value("${aliyun.region}")
    private String region;
    @Value("${aliyun.accessKeyId}")
    private String accessKeyId;
    @Value("${aliyun.accessKeySecret}")
    private String accessKeySecret;



    /**
     * 判断文件是否存在
     *
     * @param mediaDTO
     * @param companyId
     * @return
     */
    @Override
    public MediaDTO createMedia(MediaDTO mediaDTO, Long companyId) {
        String filename = mediaDTO.getFilename();
        String fileId = mediaDTO.getFileId();
        String type = mediaDTO.getType();
        ExceptionCast.cast(ObjectUtils.isEmpty(companyId), MediaErrorCode.E_140102);
        ExceptionCast.cast(StringUtil.isBlank(filename), MediaErrorCode.E_140006);
        ExceptionCast.cast(StringUtil.isBlank(fileId), MediaErrorCode.E_140007);
        ExceptionCast.cast(StringUtil.isBlank(type), MediaErrorCode.E_140004);

        LambdaQueryWrapper<Media> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.eq(Media::getFileId, fileId);
        Media media = this.getOne(queryWrapper);
        ExceptionCast.cast(!ObjectUtils.isEmpty(media), MediaErrorCode.E_140004);
        Media po = MediaConvert.INSTANCE.dto2entity(mediaDTO);
        po.setCompanyId(companyId);
        po.setAuditStatus(CourseAuditEnum.AUDIT_UNPAST_STATUS.getCode());
        boolean save = this.save(po);
        ExceptionCast.cast(!save, MediaErrorCode.E_140001);
        Media byId = this.getById(po.getId());
        return MediaConvert.INSTANCE.entity2dto(byId);
    }

    /*
     *
     * @param param
     * @param queryMediaModel
     * @param companyId
     * @return
     */
    @Override
    public PageVO<MediaDTO> queryMediaPage(PageRequestParams param, QueryMediaModel queryMediaModel, Long companyId) {

        Long pageNo = param.getPageNo();
        Integer pageSize = param.getPageSize();
        if (pageNo == null || pageNo < 0) {
            pageNo = PageRequestParams.DEFAULT_PAGE_NUM;
        }
        if (pageSize == null || pageSize < 0) {
            pageSize = PageRequestParams.DEFAULT_PAGE_SIZE;
        }

        LambdaQueryWrapper<Media> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.eq(!ObjectUtils.isEmpty(companyId), Media::getCompanyId, companyId);
        queryWrapper.like(!StringUtil.isBlank(queryMediaModel.getFilename()), Media::getFilename, queryMediaModel.getFilename());
        queryWrapper.eq(!StringUtil.isBlank(queryMediaModel.getType()), Media::getType, queryMediaModel.getType());
        queryWrapper.eq(!StringUtil.isBlank(queryMediaModel.getAuditStatus()), Media::getAuditStatus, queryMediaModel.getAuditStatus());
        IPage<Media> ipage = new Page<>(pageNo, pageSize);
        IPage<Media> pageResult = this.page(ipage, queryWrapper);
        List<Media> records = pageResult.getRecords();
        List<MediaDTO> mediaDTOS = MediaConvert.INSTANCE.entitys2dtos(records);
        PageVO page = new PageVO();
        page.setPageSize(pageSize);
        page.setPage(pageNo.intValue());
        page.setCounts(pageResult.getTotal());
        page.setItems(mediaDTOS);
        return page;
    }

    /*
     *  查询媒资信息
     * @param mediaId
     * @param companyId
     * @return
     */
    @Override
    public String getMediaById(Long mediaId, Long companyId) {
        Media media = mediaCompnayVerify(mediaId, companyId);
        String fileId = media.getFileId();
        ValueOperations valueOperations = redisTemplate.opsForValue();
        String address = (String) valueOperations.get(fileId);
        if (StringUtil.isBlank(address)) {
            try {
                DefaultAcsClient defaultAcsClient = AliyunVODUtil.initVodClient(region, accessKeyId, accessKeySecret);
                GetPlayInfoResponse playInfoResponse = AliyunVODUtil.getPlayInfo(defaultAcsClient, fileId, 3600L);
                List<GetPlayInfoResponse.PlayInfo> playInfoList = playInfoResponse.getPlayInfoList();
                GetPlayInfoResponse.PlayInfo playInfo = playInfoList.get(0);
                address = playInfo.getPlayURL();
                valueOperations.set(fileId, address);
                redisTemplate.expire(fileId, 3500, TimeUnit.SECONDS);
            } catch (Exception e) {
                ExceptionCast.cast(MediaErrorCode.E_140014);
            }
        }
        return address;
    }

    private Media mediaCompnayVerify(Long mediaId, Long companyId) {
        ExceptionCast.cast(ObjectUtils.isEmpty(mediaId), MediaErrorCode.E_140005);
//        ExceptionCast.cast(ObjectUtils.isEmpty(companyId),MediaErrorCode.E_140102);
        LambdaQueryWrapper<Media> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.eq(Media::getId, mediaId);
        queryWrapper.eq(!ObjectUtils.isEmpty(companyId), Media::getCompanyId, companyId);
        Media media = this.getOne(queryWrapper);
        ExceptionCast.cast(ObjectUtils.isEmpty(media), MediaErrorCode.E_140005);
        return media;
    }

    /* 删除媒资信息
     * @param mediaId
     * @param companyId
     * @return
     */
    @Override
    @Transactional
    public boolean deleteMediaById(Long mediaId, Long companyId) {
        //1.效验数据 根据id查询的媒资信息是否存在 ,媒资信息是否在本机构
        Media media = mediaCompnayVerify(mediaId, companyId);
        //        Media media = mediaCompnayVerify(mediaId, companyId);
       /* String auditStatus = media.getAuditStatus();
        if(auditStatus!=null && !auditStatus.equals(AuditEnum.AUDIT_DISPAST_STATUS.getCode()) && !auditStatus.equals(AuditEnum.AUDIT_UNPAST_STATUS.getCode())){
            ExceptionCast.cast(MediaErrorCode.E_140102);
        }*/

        //判断是否绑定课程信息
        RestResponse<Integer> teacherMediaCount = mediaTeacherAgent.getTeacherMediaCount(mediaId);
        Integer result = teacherMediaCount.getResult();
        if(result!=null&&result>0){
            ExceptionCast.cast(MediaErrorCode.E_140003);
        }

        //删除 云服务信息
        try {
            DefaultAcsClient defaultAcsClient = AliyunVODUtil.initVodClient(region, accessKeyId, accessKeySecret);
            AliyunVODUtil.deleteVideo(defaultAcsClient,media.getFileId());
        } catch (Exception e) {
            log.error("删除云服务资源失败:{}",e.getMessage());
            ExceptionCast.cast(MediaErrorCode.E_140014);
        }

        return this.removeById(mediaId);
    }

    @Override
    public RestResponse<MediaDTO> getMedia4s(Long mediaId) {
        if (ObjectUtils.isEmpty(mediaId)) {
            return RestResponse.validfail(CommonErrorCode.E_100101);
        }
        Media media = this.getById(mediaId);
        if (ObjectUtils.isEmpty(media)) {
            return RestResponse.validfail(CommonErrorCode.E_100104);
        }
        MediaDTO dto = MediaConvert.INSTANCE.entity2dto(media);
        return RestResponse.success(dto);
    }

    /**
     * 判断核心数据
     * 判断业务数据
     * 更新状态
     * @param dto
     * @return
     */
    @Override
    @Transactional
    public boolean modifyMediaAudit(MediaDTO dto) {
        String audit = dto.getAuditStatus();
        String auditMind = dto.getAuditMind();
        Long id = dto.getId();
        if (ObjectUtils.isEmpty(id) || StringUtil.isBlank(audit) || StringUtil.isBlank(auditMind)) {
            ExceptionCast.cast(CommonErrorCode.E_100101);
        }
//        CourseAuditEnum
        if(!audit.equals(AuditEnum.AUDIT_PASTED_STATUS.getCode())&& !audit.equals(AuditEnum.AUDIT_DISPAST_STATUS.getCode())){
            ExceptionCast.cast(CommonErrorCode.E_100107);
        }

        Media media = this.getById(id);
        ExceptionCast.cast(ObjectUtils.isEmpty(media), MediaErrorCode.E_140005);
        ExceptionCast.cast(ObjectUtils.nullSafeEquals(media.getStatus(),
                CommonEnum.DELETE_FLAG.getCode().toString()),
                    MediaErrorCode.E_140008
                );
        Long companyId = media.getCompanyId();
        ExceptionCast.cast(ObjectUtils.isEmpty(companyId),MediaErrorCode.E_140102);

        LambdaUpdateWrapper<Media> updateWrapper = Wrappers.lambdaUpdate();
        updateWrapper.set(Media::getAuditStatus,audit);
        updateWrapper.set(Media::getAuditMind,auditMind);
        updateWrapper.eq(Media::getId,id);
        return this.update(updateWrapper);
    }
}
